#include <vector>
#include <cstdlib>
#include <cassert>
#include "g1_heap.hpp"

G1Heap::G1Heap() : current_gc_epoch(0)
{
    // 分配堆空间
    heap_start = std::malloc(HEAP_SIZE);
    assert(heap_start != nullptr);

    // 初始化Region
    for (size_t i = 0; i < REGION_COUNT; i++)
    {
        void *region_start = static_cast<char *>(heap_start) + i * G1Region::get_region_size();
        regions[i] = new G1Region(region_start);
    }
}

G1Heap::~G1Heap()
{
    for (size_t i = 0; i < REGION_COUNT; i++)
    {
        delete regions[i];
    }
    std::free(heap_start);
}

void *G1Heap::allocate(size_t size)
{
    // 大对象分配
    if (size > G1Region::get_region_size() / 2)
    {
        // 查找连续的空Region
        for (size_t i = 0; i < REGION_COUNT; i++)
        {
            if (regions[i]->is_empty_region())
            {
                regions[i]->set_is_humongous(true);
                return regions[i]->allocate(size);
            }
        }
        return nullptr;
    }

    // 普通对象分配
    for (size_t i = 0; i < REGION_COUNT; i++)
    {
        if (!regions[i]->is_full() && !regions[i]->get_is_humongous())
        {
            void *result = regions[i]->allocate(size);
            if (result != nullptr)
            {
                return result;
            }
        }
    }

    collect_garbage();
    return allocate(size);
}

void G1Heap::collect_garbage()
{
    current_gc_epoch++;
    // 标记阶段
    mark_roots();
    process_mark_queue();

    // 清除阶段
    for (size_t i = 0; i < REGION_COUNT; i++)
    {
        G1Region *region = regions[i];
        if (!region->has_live_objects(current_gc_epoch))
        {
            region->mark_as_empty();
        }
    }

    // 整理阶段
    compact_live_objects();
}

void G1Heap::mark_roots()
{
    // 标记根对象

    for (void *root : roots.static_roots)
    {
        if (root != nullptr)
        {
            G1Object *obj = G1Object::from_address(root);
            if (!obj->is_marked_in_epoch(current_gc_epoch))
            {
                obj->mark_in_epoch(current_gc_epoch);
                mark_queue.push(obj);
            }
        }
    }

    // 标记线程栈
    for (void *stack_ptr : roots.stack_roots)
    {   
        if (stack_ptr!= nullptr)
        {
            G1Object *obj = G1Object::from_address(stack_ptr);
            if (!obj->is_marked_in_epoch(current_gc_epoch))
            {
                obj->mark_in_epoch(current_gc_epoch);
                mark_queue.push(obj);
            }
        }
    }

    // 标记JNI引用
    for (void *jni_ref : roots.jni_roots)
    {
        if (jni_ref!= nullptr)
        {
            G1Object *obj = G1Object::from_address(jni_ref);
            if (!obj->is_marked_in_epoch(current_gc_epoch))
            {
                obj->mark_in_epoch(current_gc_epoch);
                mark_queue.push(obj);
            }
        }
    }
}

void G1Heap::process_mark_queue()
{
    while (!mark_queue.empty())
    {
        void* current = mark_queue.pop();
        if(current==nullptr)continue;
        G1Object *obj = G1Object::from_address(current);
        // 获取对象的引用字段
        std::vector<void*> references= get_object_references(obj);
        // 处理每个引用
        for (void *ref : references)
        {
            if (ref!= nullptr)
            {
                G1Object *ref_obj = G1Object::from_address(ref);
                if (!ref_obj->is_marked_in_epoch(current_gc_epoch))
                {
                    ref_obj->mark_in_epoch(current_gc_epoch);
                    mark_queue.push(ref);
                }
            }
        }
    }  
}


std::vector<void*> G1Heap::get_object_references(G1Object *obj)
{
    std::vector<void*> references;
    // 获取对象的类信息
    Klass *klass = static_cast<Klass*>(obj->get_header().klass_pointer);
    if(klass==nullptr)return references;
    
    // 遍历对象的引用字段
    size_t* fields=reinterpret_cast<size_t*>(obj+1); // 跳过对象头
    size_t field_count=klass->reference_field_count;
    for (size_t i = 0; i < field_count; i++)
    {
        void* ref=reinterpret_cast<void*>(fields[i]);
        if(ref!=nullptr&&is_valid_heap_pointer(ref)){
            references.push_back(ref);
        }
    }
    return references;
}



bool G1Heap::is_valid_heap_pointer(void *ptr)
{
    return ptr >= heap_start && ptr < static_cast<char *>(heap_start) + HEAP_SIZE;
}


void G1Heap::compact_live_objects()
{
    for (size_t i = 0; i < REGION_COUNT; i++)
    {
        G1Region *region = regions[i];
        if (!region->is_empty_region()&&!region->get_is_humongous())
        {
           // 占位符 
        }
    }
}